#
# Ensembl module for Bio::EnsEMBL::Funcgen::ProbeSet
#

=head1 LICENSE

Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
Copyright [2016-2019] EMBL-European Bioinformatics Institute

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

=head1 CONTACT

  Please email comments or questions to the public Ensembl
  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.

  Questions may also be sent to the Ensembl help desk at
  <http://www.ensembl.org/Help/Contact>.

=head1 NAME

Bio::EnsEMBL::Funcgen::ProbeSet - A module to represent a probeset.

=head1 SYNOPSIS

 use Bio::EnsEMBL::Registry;
 use Bio::EnsEMBL::Funcgen::ProbeSet;


 my $reg = Bio::EnsEMBL::Registry->load_adaptors_from_db(
  -host    => 'ensembldb.ensembl.org',
  -user    => 'anonymous'
  );

 my $pset_adaptor = $reg->get_adaptor($species, 'funcgen', 'ProbeSet');

 ### Creating/storing a ProbeSet ###

 my $probe_set = Bio::EnsEMBL::Funcgen::ProbeSet->new(
    -NAME          => 'ProbeSet-1',
    -SIZE          => 1,
    -FAMILY        => "ENCODE REGIONS",#optional
  );

 $pset_adaptor->store($probe_set);

 ### Fetching associated transcripts ###
 # Generated by the Ensembl array mapping pipeline

 my @dbentries     = @{$probe_set->fetch_all_Transcript_DBEntries};
 my $trans_adaptor = $reg->get_adpator($species, 'core', 'Transcript');

 foreach my $dbe(@dbentries){

    my $tx = $trans_adaptor->fetch_by_stable_id($dbe->primary_id);
   
    #Print the transcript info and the linkage annotation
    print $tx->stable_id."\t".$probe_set->name.' '.$dbe->linkage_annotation."\n";
 }

 #Alternatively these annotations are also available in a transcript centric manner
 #using the ProbeSetAdaptor


=head1 DESCRIPTION

A ProbeSet object represents a set of probes on a microarray. The
data (currently the name, size, and family) are stored in the probe_set 
table. ProbeSets are only really relevant for Affy probes, or when 
avaliable these will be analagous to Nimblegen feature sets.

For Affy arrays, a probeset can be part of more than one array, containing unique
probes. 

=head1 SEE ALSO

  Bio::EnsEMBL::Funcgen::ProbeSetAdaptor
  ensembl-funcgen/scripts/examples/microarray_annotation_example.pl

  Or for details on how to run the array mapping pipeline see:
  ensembl-funcgen/docs/array_mapping.txt

=cut

package Bio::EnsEMBL::Funcgen::ProbeSet;

use strict;
use warnings;
use Bio::EnsEMBL::Utils::Argument  qw( rearrange ) ;
use Bio::EnsEMBL::Utils::Exception qw( throw warning deprecate );

use base qw( Bio::EnsEMBL::Funcgen::Storable );

=head2 new

  Arg [-NAME]           : string - probeset name
  Arg [-SIZE]           : int - probe set size
        Will be the same for all probes sets if same probe set
        is on multiple arrays.
  Arg [-FAMILY]         : string - probe set family, generic descriptor for probe set e.g. ENCODE REGIONS, RANDOM
        Will be the same for all probes sets if same probe set is on multiple arrays.
  Example    : my $probeset = Bio::EnsEMBL::Funcgen::ProbeSet->new(
                -NAME          => 'ProbeSet-1',
                -SIZE          => 1,
                -FAMILY        => "ENCODE_REGIONS",
               );
  Description: Creates a new Bio::EnsEMBL::Funcgen::ProbeSet object.
  Returntype : Bio::EnsEMBL::Funcgen::ProbeSet
  Exceptions : Throws if not supplied with probeset name and array chip id(s)
  Caller     : General
  Status     : Medium Risk

=cut

sub new {
  my $caller = shift;

  my $class = ref($caller) || $caller;
  my $self = $class->SUPER::new(@_);

  my (
    $name, 
    $size,
    $family
  ) = rearrange([
    'NAME', 
    'SIZE',
    'FAMILY',
  ], @_);

  $self->name($name)     if defined $name;
  $self->family($family) if defined $family;
  $self->size($size)     if defined $size;

  return $self;
}

=head2 get_all_Arrays

  Args       : None
  Example    : my $arrays = $probeset->get_all_Arrays();
  Description: Returns all arrays that this probeset is part of. Only works if the
               probeset was retrieved from the database or created using
               add_Array_probename.
  Returntype : Listref of Bio::EnsEMBL::Funcgen::Array objects
  Exceptions : None
  Caller     : General
  Status     : Medium Risk

=cut

sub get_all_Arrays {
  my $self = shift;

  if (defined $self->{'arrays'}) {
    return $self->{'arrays'};
  } else {
    $self->{arrays} = $self->adaptor->db->get_ArrayAdaptor->fetch_all_by_ProbeSet($self);
  }
  return $self->{arrays};
}

sub get_Array {
  my $self = shift;
  my $arrays = $self->get_all_Arrays;
  
  if (scalar @$arrays != 1) {
    die("The probe set links to more than one array!");
  }
  return $arrays->[0];
}

=head2 get_all_Probes

  Args       : None
  Example    : my @probes = @{$probeset->get_all_Probes();
  Description: Returns all probes belonging to this ProbeSet
  Returntype : Listref of Bio::EnsEMBL::Funcgen::Probe objects
  Exceptions : None
  Caller     : General
  Status     : At Risk

=cut

sub get_all_Probes {
  my $self = shift;

  if (defined $self->{'probes'}) {
    return $self->{'probes'};
  } 
  else{
    $self->{probes} = $self->adaptor->db->get_ProbeAdaptor->fetch_all_by_ProbeSet($self);
  }
  return $self->{probes};
}

=head2 name

  Arg [1]    : string - aprobeset name
  Example    : my $probesetname = $probeset->name('probeset-1');
  Description: Getter/Setter for the name attribute of ProbeSet objects.
  Returntype : string
  Exceptions : None
  Caller     : General
  Status     : Medium Risk

=cut

sub name {
  my $self = shift;
  $self->{'name'} = shift if @_;
  return $self->{'name'};
}


=head2 family

  Arg [1]    : (optional) string - family
  Example    : my $family = $probe->family();
  Description: Getter and setter of family attribute for ProbeSet
               objects. e.g. EXPERIMENTAL or CONTROL
  Returntype : string
  Exceptions : None
  Caller     : General
  Status     : Medium Risk

=cut

sub family {
  my $self = shift;
  $self->{'family'} = shift if @_;
  return $self->{'family'};
}

=head2 size

  Arg [1]    : (optional) int - probeset size
  Example    : my $probeset_size = $probeset->size();
  Description: Getter and setter of probeset size attribute for ProbeSet
               objects.
  Returntype : int
  Exceptions : None
  Caller     : General
  Status     : Medium Risk

=cut

sub size {
  my $self = shift;
  $self->{'size'} = shift if @_;
  return $self->{'size'};
}

sub get_all_ProbeSetTranscriptMappings {
  my $self = shift;
  return $self->adaptor->db->get_ProbeSetTranscriptMappingAdaptor->fetch_all_by_probe_set_id($self->dbID);
}

sub fetch_all_ProbeSetTranscriptMappings {
  my $self = shift;
  my $msg = 'It will be removed in release 104.' . "\n" . 'Please use '
      . ref($self) . '::get_all_ProbeSetTranscriptMappings instead.';
  deprecate($msg);
  return $self->get_all_ProbeSetTranscriptMappings;
}

1;

